home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / pax / part05 < prev    next >
Encoding:
Internet Message Format  |  1989-02-02  |  36.8 KB

  1. Subject:  v17i078:  Usenix/IEEE POSIX replacement for TAR and CPIO, Part05/06
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Mark H. Colburn <mark@jhereg.jhereg.mn.org>
  6. Posting-number: Volume 17, Issue 78
  7. Archive-name: pax/part05
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 5 (of 6)."
  16. # Contents:  buffer.c paxdir.c
  17. # Wrapped by mark@jhereg on Tue Dec 27 19:37:59 1988
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f buffer.c -a "${1}" != "-c" ; then 
  20.   echo shar: Will not over-write existing file \"buffer.c\"
  21. else
  22. echo shar: Extracting \"buffer.c\" \(17360 characters\)
  23. sed "s/^X//" >buffer.c <<'END_OF_buffer.c'
  24. X/* $Source: /u/mark/src/pax/RCS/buffer.c,v $
  25. X *
  26. X * $Revision: 1.1 $
  27. X *
  28. X * buffer.c - Buffer management functions
  29. X *
  30. X * DESCRIPTION
  31. X *
  32. X *    These functions handle buffer manipulations for the archiving
  33. X *    formats.  Functions are provided to get memory for buffers, 
  34. X *    flush buffers, read and write buffers and de-allocate buffers.  
  35. X *    Several housekeeping functions are provided as well to get some 
  36. X *    information about how full buffers are, etc.
  37. X *
  38. X * AUTHOR
  39. X *
  40. X *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  41. X *
  42. X * Sponsored by The USENIX Association for public distribution. 
  43. X *
  44. X * Copyright (c) 1989 Mark H. Colburn.
  45. X * All rights reserved.
  46. X *
  47. X * Redistribution and use in source and binary forms are permitted
  48. X * provided that the above copyright notice is duplicated in all such 
  49. X * forms and that any documentation, advertising materials, and other 
  50. X * materials related to such distribution and use acknowledge that the 
  51. X * software was developed * by Mark H. Colburn and sponsored by The 
  52. X * USENIX Association. 
  53. X *
  54. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  55. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  56. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  57. X *
  58. X * $Log:    buffer.c,v $
  59. X * Revision 1.1  88/12/23  18:02:01  mark
  60. X * Initial revision
  61. X * 
  62. X */
  63. X
  64. X#ifndef lint
  65. Xstatic char *ident = "$Id: buffer.c,v 1.1 88/12/23 18:02:01 mark Rel $";
  66. Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  67. X#endif /* ! lint */
  68. X
  69. X
  70. X/* Headers */
  71. X
  72. X#include "pax.h"
  73. X
  74. X
  75. X/* Function Prototypes */
  76. X
  77. X#ifdef __STDC__
  78. X
  79. Xstatic int ar_write(int, char *, uint);
  80. Xstatic void buf_pad(OFFSET);
  81. Xstatic int indata(int, OFFSET, char *);
  82. Xstatic void outflush(void);
  83. Xstatic void buf_use(uint);
  84. Xstatic int buf_in_avail(char **, uint *);
  85. Xstatic uint buf_out_avail(char **);
  86. X
  87. X#else /* !__STDC__ */
  88. X
  89. Xstatic int ar_write();
  90. Xstatic void buf_pad();
  91. Xstatic int indata();
  92. Xstatic void outflush();
  93. Xstatic void buf_use();
  94. Xstatic int buf_in_avail();
  95. Xstatic uint buf_out_avail();
  96. X
  97. X#endif /* __STDC__ */
  98. X
  99. X
  100. X/* inentry - install a single archive entry
  101. X *
  102. X * DESCRIPTION
  103. X *
  104. X *    Inentry reads an archive entry from the archive file and writes it
  105. X *    out the the named file.  If we are in PASS mode during archive
  106. X *    processing, the pass() function is called, otherwise we will
  107. X *    extract from the archive file.
  108. X *
  109. X *    Inentry actaully calls indata to process the actual data to the
  110. X *    file.
  111. X *
  112. X * PARAMETERS
  113. X *
  114. X *    char    *name    - name of the file to extract from the archive
  115. X *    Stat    *asb    - stat block of the file to be extracted from the
  116. X *              archive.
  117. X *
  118. X * RETURNS
  119. X *
  120. X *     Returns zero if successful, -1 otherwise. 
  121. X */
  122. X
  123. X#ifdef __STDC__
  124. X
  125. Xint inentry(char *name, Stat *asb)
  126. X
  127. X#else
  128. X
  129. Xint inentry(name, asb)
  130. Xchar           *name;
  131. XStat           *asb;
  132. X
  133. X#endif
  134. X{
  135. X    Link           *linkp;
  136. X    int             ifd;
  137. X    int             ofd;
  138. X    time_t          tstamp[2];
  139. X
  140. X    if ((ofd = openo(name, asb, linkp = linkfrom(name, asb), 0)) > 0) {
  141. X    if (asb->sb_size || linkp == NULL || linkp->l_size == 0) {
  142. X        close(indata(ofd, asb->sb_size, name));
  143. X    } else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) {
  144. X        warn(linkp->l_path->p_name, syserr());
  145. X    } else {
  146. X        passdata(linkp->l_path->p_name, ifd, name, ofd);
  147. X        close(ifd);
  148. X        close(ofd);
  149. X    }
  150. X    } else {
  151. X    return(buf_skip((OFFSET) asb->sb_size) >= 0);
  152. X    }
  153. X    tstamp[0] = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0);
  154. X    tstamp[1] = f_modification_time ? asb->sb_mtime : time((time_t *) 0);
  155. X    utime(name, tstamp);
  156. X    return (0);
  157. X}
  158. X
  159. X
  160. X/* outdata - write archive data
  161. X *
  162. X * DESCRIPTION
  163. X *
  164. X *    Outdata transfers data from the named file to the archive buffer.
  165. X *    It knows about the file padding which is required by tar, but no
  166. X *    by cpio.  Outdata continues after file read errors, padding with 
  167. X *    null characters if neccessary.   Closes the input file descriptor 
  168. X *    when finished.
  169. X *
  170. X * PARAMETERS
  171. X *
  172. X *    int    fd    - file descriptor of file to read data from
  173. X *    char   *name    - name of file
  174. X *    OFFSET    size    - size of the file
  175. X *
  176. X */
  177. X
  178. X#ifdef __STDC__
  179. X
  180. Xvoid outdata(int fd, char *name, OFFSET size)
  181. X
  182. X#else
  183. X
  184. Xvoid outdata(fd, name, size)
  185. Xint             fd;
  186. Xchar           *name;
  187. XOFFSET          size;
  188. X
  189. X#endif
  190. X{
  191. X    uint            chunk;
  192. X    int             got;
  193. X    int             oops;
  194. X    uint            avail;
  195. X    int            pad;
  196. X    char           *buf;
  197. X
  198. X    oops = got = 0;
  199. X    if (pad = (size % BLOCKSIZE)) {
  200. X    pad = (BLOCKSIZE - pad);
  201. X    }
  202. X    while (size) {
  203. X    avail = buf_out_avail(&buf);
  204. X    size -= (chunk = size < avail ? (uint) size : avail);
  205. X    if (oops == 0 && (got = read(fd, buf, (unsigned int) chunk)) < 0) {
  206. X        oops = -1;
  207. X        warn(name, syserr());
  208. X        got = 0;
  209. X    }
  210. X    if (got < chunk) {
  211. X        if (oops == NULL) {
  212. X        oops = -1;
  213. X        }
  214. X        warn(name, "Early EOF");
  215. X        while (got < chunk) {
  216. X        buf[got++] = '\0';
  217. X        }
  218. X    }
  219. X    buf_use(chunk);
  220. X    }
  221. X    close(fd);
  222. X    if (ar_format == TAR) {
  223. X    buf_pad((OFFSET) pad);
  224. X    }
  225. X}
  226. X
  227. X
  228. X/* write_eot -  write the end of archive record(s)
  229. X *
  230. X * DESCRIPTION
  231. X *
  232. X *    Write out an End-Of-Tape record.  We actually zero at least one 
  233. X *    record, through the end of the block.  Old tar writes garbage after 
  234. X *    two zeroed records -- and PDtar used to.
  235. X */
  236. X
  237. X#ifdef __STDC__
  238. X
  239. Xvoid write_eot(void)
  240. X
  241. X#else
  242. X
  243. Xvoid write_eot()
  244. X
  245. X#endif
  246. X{
  247. X    OFFSET           pad;
  248. X    char            header[M_STRLEN + H_STRLEN + 1];
  249. X
  250. X    if (ar_format == TAR) {
  251. X    /* write out two zero blocks for trailer */
  252. X    pad = 2 * BLOCKSIZE;
  253. X    } else {
  254. X    if (pad = (total + M_STRLEN + H_STRLEN + TRAILZ) % BLOCKSIZE) {
  255. X        pad = BLOCKSIZE - pad;
  256. X    }
  257. X    strcpy(header, M_ASCII);
  258. X    sprintf(header + M_STRLEN, H_PRINT, 0, 0,
  259. X               0, 0, 0, 1, 0, (time_t) 0, TRAILZ, pad);
  260. X    outwrite(header, M_STRLEN + H_STRLEN);
  261. X    outwrite(TRAILER, TRAILZ);
  262. X    }
  263. X    buf_pad((OFFSET) pad);
  264. X    outflush();
  265. X}
  266. X
  267. X/* outwrite -  write archive data
  268. X *
  269. X * DESCRIPTION
  270. X *
  271. X *    Writes out data in the archive buffer to the archive file.  The
  272. X *    buffer index and the total byte count are incremented by the number
  273. X *    of data bytes written.
  274. X *
  275. X * PARAMETERS
  276. X *    
  277. X *    char   *idx    - pointer to data to write
  278. X *    uint    len    - length of the data to write
  279. X */
  280. X
  281. X#ifdef __STDC__
  282. X
  283. Xvoid outwrite(char *idx, uint len)
  284. X
  285. X#else
  286. X
  287. Xvoid outwrite(idx, len)
  288. Xchar           *idx;    /* pointer to data to write */
  289. Xuint            len;    /* length of data to write */
  290. X
  291. X#endif
  292. X{
  293. X    uint            have;
  294. X    uint            want;
  295. X    char           *endx;
  296. X
  297. X    endx = idx + len;
  298. X    while (want = endx - idx) {
  299. X    if (bufend - bufidx < 0) {
  300. X        fatal("Buffer overlow in out_write\n");
  301. X    }
  302. X    if ((have = bufend - bufidx) == 0) {
  303. X        outflush();
  304. X    }
  305. X    if (have > want) {
  306. X        have = want;
  307. X    }
  308. X    memcpy(bufidx, idx, (int) have);
  309. X    bufidx += have;
  310. X    idx += have;
  311. X    total += have;
  312. X    }
  313. X}
  314. X
  315. X
  316. X/* passdata - copy data to one file
  317. X *
  318. X * DESCRIPTION
  319. X *
  320. X *    Copies a file from one place to another.  Doesn't believe in input 
  321. X *    file descriptor zero (see description of kludge in openi() comments). 
  322. X *    Closes the provided output file descriptor. 
  323. X *
  324. X * PARAMETERS
  325. X *
  326. X *    char    *from    - input file name (old file)
  327. X *    int    ifd    - input file descriptor
  328. X *    char    *to    - output file name (new file)
  329. X *    int    ofd    - output file descriptor
  330. X */
  331. X
  332. X#ifdef __STDC__
  333. X
  334. Xvoid passdata(char *from, int ifd, char *to, int ofd)
  335. X
  336. X#else
  337. X
  338. Xvoid passdata(from, ifd, to, ofd)
  339. Xchar           *from;
  340. Xint             ifd;
  341. Xchar           *to;
  342. Xint             ofd;
  343. X
  344. X#endif
  345. X{
  346. X    int             got;
  347. X    int             sparse;
  348. X    char            block[BUFSIZ];
  349. X
  350. X    if (ifd) {
  351. X    lseek(ifd, (OFFSET) 0, 0);
  352. X    sparse = 0;
  353. X    while ((got = read(ifd, block, sizeof(block))) > 0
  354. X           && (sparse = ar_write(ofd, block, (uint) got)) >= 0) {
  355. X        total += got;
  356. X    }
  357. X    if (got) {
  358. X        warn(got < 0 ? from : to, syserr());
  359. X    } else if (sparse > 0
  360. X         && (lseek(ofd, (OFFSET)(-sparse), 1) < 0
  361. X             || write(ofd, block, (uint) sparse) != sparse)) {
  362. X        warn(to, syserr());
  363. X    }
  364. X    }
  365. X    close(ofd);
  366. X}
  367. X
  368. X
  369. X/* buf_allocate - get space for the I/O buffer 
  370. X *
  371. X * DESCRIPTION
  372. X *
  373. X *    buf_allocate allocates an I/O buffer using malloc.  The resulting
  374. X *    buffer is used for all data buffering throughout the program.
  375. X *    Buf_allocate must be called prior to any use of the buffer or any
  376. X *    of the buffering calls.
  377. X *
  378. X * PARAMETERS
  379. X *
  380. X *    int    size    - size of the I/O buffer to request
  381. X *
  382. X * ERRORS
  383. X *
  384. X *    If an invalid size is given for a buffer or if a buffer of the 
  385. X *    required size cannot be allocated, then the function prints out an 
  386. X *    error message and returns a non-zero exit status to the calling 
  387. X *    process, terminating the program.
  388. X *
  389. X */
  390. X
  391. X#ifdef __STDC__
  392. X
  393. Xvoid buf_allocate(OFFSET size)
  394. X
  395. X#else
  396. X
  397. Xvoid buf_allocate(size)
  398. XOFFSET            size;
  399. X
  400. X#endif
  401. X{
  402. X    extern char *malloc();
  403. X    
  404. X    if (size <= 0) {
  405. X    fatal("invalid value for blocksize");
  406. X    }
  407. X    if ((bufstart = malloc((unsigned) size)) == NULL) {
  408. X    fatal("Cannot allocate I/O buffer");
  409. X    }
  410. X    bufend = bufidx = bufstart;
  411. X    bufend += size;
  412. X}
  413. X
  414. X
  415. X/* buf_skip - skip input archive data
  416. X *
  417. X * DESCRIPTION
  418. X *
  419. X *    Buf_skip skips past archive data.  It is used when the length of
  420. X *    the archive data is known, and we do not wish to process the data.
  421. X *
  422. X * PARAMETERS
  423. X *
  424. X *    OFFSET    len    - number of bytes to skip
  425. X *
  426. X * RETURNS
  427. X *
  428. X *     Returns zero under normal circumstances, -1 if unreadable data is 
  429. X *     encountered. 
  430. X */
  431. X
  432. X#ifdef __STDC__
  433. X
  434. Xint buf_skip(OFFSET len)
  435. X
  436. X#else
  437. X
  438. Xint buf_skip(len)
  439. XOFFSET           len;
  440. X
  441. X#endif
  442. X{
  443. X    uint            chunk;
  444. X    int             corrupt = 0;
  445. X
  446. X    while (len) {
  447. X    if (bufend - bufidx < 0) {
  448. X        fatal("Buffer overlow in buf_skip\n");
  449. X    }
  450. X    while ((chunk = bufend - bufidx) == 0) {
  451. X        corrupt |= ar_read();
  452. X    }
  453. X    if (chunk > len) {
  454. X        chunk = len;
  455. X    }
  456. X    bufidx += chunk;
  457. X    len -= chunk;
  458. X    total += chunk;
  459. X    }
  460. X    return (corrupt);
  461. X}
  462. X
  463. X
  464. X/* buf_read - read a given number of characters from the input archive
  465. X *
  466. X * DESCRIPTION
  467. X *
  468. X *    Reads len number of characters from the input archive and
  469. X *    stores them in the buffer pointed at by dst.
  470. X *
  471. X * PARAMETERS
  472. X *
  473. X *    char   *dst    - pointer to buffer to store data into
  474. X *    uint    len    - length of data to read
  475. X *
  476. X * RETURNS
  477. X *
  478. X *     Returns zero with valid data, -1 if unreadable portions were 
  479. X *    replaced by null characters. 
  480. X */
  481. X
  482. X#ifdef __STDC__
  483. X
  484. Xint buf_read(char *dst, uint len)
  485. X
  486. X#else
  487. X
  488. Xint buf_read(dst, len)
  489. Xchar           *dst;
  490. Xuint            len;
  491. X
  492. X#endif
  493. X{
  494. X    int             have;
  495. X    int             want;
  496. X    int             corrupt = 0;
  497. X    char           *endx = dst + len;
  498. X
  499. X    while (want = endx - dst) {
  500. X    if (bufend - bufidx < 0) {
  501. X        fatal("Buffer overlow in buf_read\n");
  502. X    }
  503. X    while ((have = bufend - bufidx) == 0) {
  504. X        have = 0;
  505. X        corrupt |= ar_read();
  506. X    }
  507. X    if (have > want) {
  508. X        have = want;
  509. X    }
  510. X    memcpy(dst, bufidx, have);
  511. X    bufidx += have;
  512. X    dst += have;
  513. X    total += have;
  514. X    }
  515. X    return (corrupt);
  516. X}
  517. X
  518. X
  519. X/* indata - install data from an archive
  520. X *
  521. X * DESCRIPTION
  522. X *
  523. X *    Indata writes size bytes of data from the archive buffer to the output 
  524. X *    file specified by fd.  The filename which is being written, pointed
  525. X *    to by name is provided only for diagnostics.
  526. X *
  527. X * PARAMETERS
  528. X *
  529. X *    int    fd    - output file descriptor
  530. X *    OFFSET    size    - number of bytes to write to output file
  531. X *    char    *name    - name of file which corresponds to fd
  532. X *
  533. X * RETURNS
  534. X *
  535. X *     Returns given file descriptor. 
  536. X */
  537. X
  538. X#ifdef __STDC__
  539. X
  540. Xstatic int indata(int fd, OFFSET size, char *name)
  541. X
  542. X#else
  543. X
  544. Xstatic int indata(fd, size, name)
  545. Xint             fd;
  546. XOFFSET          size;
  547. Xchar           *name;
  548. X
  549. X#endif
  550. X{
  551. X    uint            chunk;
  552. X    char           *oops;
  553. X    int             sparse;
  554. X    int             corrupt;
  555. X    char           *buf;
  556. X    uint            avail;
  557. X
  558. X    corrupt = sparse = 0;
  559. X    oops = NULL;
  560. X    while (size) {
  561. X    corrupt |= buf_in_avail(&buf, &avail);
  562. X    size -= (chunk = size < avail ? (uint) size : avail);
  563. X    if (oops == NULL && (sparse = ar_write(fd, buf, chunk)) < 0) {
  564. X        oops = syserr();
  565. X    }
  566. X    buf_use(chunk);
  567. X    }
  568. X    if (corrupt) {
  569. X    warn(name, "Corrupt archive data");
  570. X    }
  571. X    if (oops) {
  572. X    warn(name, oops);
  573. X    } else if (sparse > 0 && (lseek(fd, (OFFSET) - 1, 1) < 0
  574. X                  || write(fd, "", 1) != 1)) {
  575. X    warn(name, syserr());
  576. X    }
  577. X    return (fd);
  578. X}
  579. X
  580. X
  581. X/* outflush - flush the output buffer
  582. X *
  583. X * DESCRIPTION
  584. X *
  585. X *    The output buffer is written, if there is anything in it, to the
  586. X *    archive file.
  587. X */
  588. X
  589. X#ifdef __STDC__
  590. X
  591. Xstatic void outflush(void)
  592. X
  593. X#else
  594. X
  595. Xstatic void outflush()
  596. X
  597. X#endif
  598. X{
  599. X    char           *buf;
  600. X    int             got;
  601. X    uint            len;
  602. X
  603. X    /* if (bufidx - buf > 0) */
  604. X    for (buf = bufstart; len = bufidx - buf;) {
  605. X        if ((got = write(archivefd, buf, MIN(len, blocksize))) > 0) {
  606. X        buf += got;
  607. X        } else if (got < 0) {
  608. X        next(AR_WRITE);
  609. X        }
  610. X    }
  611. X    bufend = (bufidx = bufstart) + blocksize;
  612. X}
  613. X
  614. X
  615. X/* ar_read - fill the archive buffer
  616. X *
  617. X * DESCRIPTION
  618. X *
  619. X *     Remembers mid-buffer read failures and reports them the next time 
  620. X *    through.  Replaces unreadable data with null characters.   Resets
  621. X *    the buffer pointers as appropriate.
  622. X *
  623. X * RETURNS
  624. X *
  625. X *    Returns zero with valid data, -1 otherwise. 
  626. X */
  627. X
  628. X#ifdef __STDC__
  629. X
  630. Xint ar_read(void)
  631. X
  632. X#else
  633. X
  634. Xint ar_read()
  635. X
  636. X#endif
  637. X{
  638. X    int             got;
  639. X    static int      failed;
  640. X
  641. X    bufend = bufidx = bufstart;
  642. X    if (!failed) {
  643. X    if (areof) {
  644. X        if (total == 0) {
  645. X        fatal("No input");
  646. X        } else {
  647. X        next(AR_READ);
  648. X        }
  649. X    }
  650. X    while (!failed && !areof && bufstart + blocksize - bufend >= blocksize) {
  651. X        if ((got = read(archivefd, bufend, (unsigned int) blocksize)) > 0) {
  652. X        bufend += got;
  653. X        } else if (got < 0) {
  654. X        failed = -1;
  655. X        warnarch(syserr(), (OFFSET) 0 - (bufend - bufidx));
  656. X        } else {
  657. X        ++areof;
  658. X        }
  659. X    }
  660. X    }
  661. X    if (failed && bufend == bufstart) {
  662. X    failed = 0;
  663. X    for (got = 0; got < blocksize; ++got) {
  664. X        *bufend++ = '\0';
  665. X    }
  666. X    return (-1);
  667. X    }
  668. X    return (0);
  669. X}
  670. X
  671. X
  672. X/* ar_write - write a filesystem block
  673. X *
  674. X * DESCRIPTION
  675. X *
  676. X *     Writes len bytes of data data from the specified buffer to the 
  677. X *    specified file.   Seeks past sparse blocks. 
  678. X *
  679. X * PARAMETERS
  680. X *
  681. X *    int     fd    - file to write to
  682. X *    char   *buf    - buffer to get data from
  683. X *    uint    len    - number of bytes to transfer
  684. X *
  685. X * RETURNS
  686. X *
  687. X *    Returns 0 if the block was written, the given length for a sparse 
  688. X *    block or -1 if unsuccessful. 
  689. X */
  690. X
  691. X#ifdef __STDC__
  692. X
  693. Xstatic int ar_write(int fd, char *buf, uint len)
  694. X
  695. X#else
  696. X
  697. Xstatic int ar_write(fd, buf, len)
  698. Xint             fd;
  699. Xchar           *buf;
  700. Xuint            len;
  701. X
  702. X#endif
  703. X{
  704. X    char           *bidx;
  705. X    char           *bend;
  706. X
  707. X    bend = (bidx = buf) + len;
  708. X    while (bidx < bend) {
  709. X    if (*bidx++) {
  710. X        return (write(fd, buf, len) == len ? 0 : -1);
  711. X    }
  712. X    }
  713. X    return (lseek(fd, (OFFSET) len, 1) < 0 ? -1 : len);
  714. X}
  715. X
  716. X
  717. X/* buf_pad - pad the archive buffer
  718. X *
  719. X * DESCRIPTION
  720. X *
  721. X *    Buf_pad writes len zero bytes to the archive buffer in order to 
  722. X *    pad it.
  723. X *
  724. X * PARAMETERS
  725. X *
  726. X *    OFFSET    pad    - number of zero bytes to pad
  727. X *
  728. X */
  729. X
  730. X#ifdef __STDC__
  731. X
  732. Xstatic void buf_pad(OFFSET pad)
  733. X
  734. X#else
  735. X
  736. Xstatic void buf_pad(pad)
  737. XOFFSET           pad;
  738. X
  739. X#endif
  740. X{
  741. X    int             idx;
  742. X    int             have;
  743. X
  744. X    while (pad) {
  745. X    if ((have = bufend - bufidx) > pad) {
  746. X        have = pad;
  747. X    }
  748. X    for (idx = 0; idx < have; ++idx) {
  749. X        *bufidx++ = '\0';
  750. X    }
  751. X    total += have;
  752. X    pad -= have;
  753. X    if (bufend - bufidx == 0) {
  754. X        outflush();
  755. X    }
  756. X    }
  757. X}
  758. X
  759. X
  760. X/* buf_use - allocate buffer space
  761. X *
  762. X * DESCRIPTION
  763. X *
  764. X *    Buf_use marks space in the buffer as being used; advancing both the
  765. X *    buffer index (bufidx) and the total byte count (total).
  766. X *
  767. X * PARAMETERS
  768. X *
  769. X *    uint    len    - Amount of space to allocate in the buffer
  770. X */
  771. X
  772. X#ifdef __STDC__
  773. X
  774. Xstatic void buf_use(uint len)
  775. X
  776. X#else
  777. X
  778. Xstatic void buf_use(len)
  779. Xuint            len;
  780. X
  781. X#endif
  782. X{
  783. X    bufidx += len;
  784. X    total += len;
  785. X}
  786. X
  787. X
  788. X/* buf_in_avail - index available input data within the buffer
  789. X *
  790. X * DESCRIPTION
  791. X *
  792. X *    Buf_in_avail fills the archive buffer, and points the bufp
  793. X *    parameter at the start of the data.  The lenp parameter is
  794. X *    modified to contain the number of bytes which were read.
  795. X *
  796. X * PARAMETERS
  797. X *
  798. X *    char   **bufp    - pointer to the buffer to read data into
  799. X *    uint    *lenp    - pointer to the number of bytes which were read
  800. X *              (returned to the caller)
  801. X *
  802. X * RETURNS
  803. X *
  804. X *     Stores a pointer to the data and its length in given locations. 
  805. X *    Returns zero with valid data, -1 if unreadable portions were 
  806. X *    replaced with nulls. 
  807. X *
  808. X * ERRORS
  809. X *
  810. X *    If an error occurs in ar_read, the error code is returned to the
  811. X *    calling function.
  812. X *
  813. X */
  814. X
  815. X#ifdef __STDC__
  816. X
  817. Xstatic int buf_in_avail(char **bufp, uint *lenp)
  818. X
  819. X#else
  820. X
  821. Xstatic int buf_in_avail(bufp, lenp)
  822. Xchar          **bufp;
  823. Xuint           *lenp;
  824. X
  825. X#endif
  826. X{
  827. X    uint            have;
  828. X    int             corrupt = 0;
  829. X
  830. X    while ((have = bufend - bufidx) == 0) {
  831. X    corrupt |= ar_read();
  832. X    }
  833. X    *bufp = bufidx;
  834. X    *lenp = have;
  835. X    return (corrupt);
  836. X}
  837. X
  838. X
  839. X/* buf_out_avail  - index buffer space for archive output
  840. X *
  841. X * DESCRIPTION
  842. X *
  843. X *     Stores a buffer pointer at a given location. Returns the number 
  844. X *    of bytes available. 
  845. X *
  846. X * PARAMETERS
  847. X *
  848. X *    char    **bufp    - pointer to the buffer which is to be stored
  849. X *
  850. X * RETURNS
  851. X *
  852. X *     The number of bytes which are available in the buffer.
  853. X *
  854. X */
  855. X
  856. X#ifdef __STDC__
  857. X
  858. Xstatic uint buf_out_avail(char **bufp)
  859. X
  860. X#else
  861. X
  862. Xstatic uint buf_out_avail(bufp)
  863. Xchar          **bufp;
  864. X
  865. X#endif
  866. X{
  867. X    int             have;
  868. X
  869. X    if (bufend - bufidx < 0) {
  870. X    fatal("Buffer overlow in buf_out_avail\n");
  871. X    }
  872. X    if ((have = bufend - bufidx) == 0) {
  873. X    outflush();
  874. X    }
  875. X    *bufp = bufidx;
  876. X    return (have);
  877. X}
  878. END_OF_buffer.c
  879. if test 17360 -ne `wc -c <buffer.c`; then
  880.     echo shar: \"buffer.c\" unpacked with wrong size!
  881. fi
  882. # end of overwriting check
  883. fi
  884. if test -f paxdir.c -a "${1}" != "-c" ; then 
  885.   echo shar: Will not over-write existing file \"paxdir.c\"
  886. else
  887. echo shar: Extracting \"paxdir.c\" \(16936 characters\)
  888. sed "s/^X//" >paxdir.c <<'END_OF_paxdir.c'
  889. X/*
  890. X    opendir -- open a directory stream
  891. X  
  892. X    last edit:    16-Jun-1987    D A Gwyn
  893. X*/
  894. X
  895. X#include    <sys/errno.h>
  896. X#include    <sys/types.h>
  897. X#include    <sys/stat.h>
  898. X#include    "paxdir.h"
  899. X
  900. X#ifdef BSD_SYSV
  901. X/*
  902. X    <sys/_dir.h> -- definitions for 4.2,4.3BSD directories
  903. X  
  904. X    last edit:    25-Apr-1987    D A Gwyn
  905. X  
  906. X    A directory consists of some number of blocks of DIRBLKSIZ bytes each,
  907. X    where DIRBLKSIZ is chosen such that it can be transferred to disk in a
  908. X    single atomic operation (e.g., 512 bytes on most machines).
  909. X  
  910. X    Each DIRBLKSIZ-byte block contains some number of directory entry
  911. X    structures, which are of variable length.  Each directory entry has the
  912. X    beginning of a (struct direct) at the front of it, containing its
  913. X    filesystem-unique ident number, the length of the entry, and the length
  914. X    of the name contained in the entry.  These are followed by the NUL-
  915. X    terminated name padded to a (long) boundary with 0 bytes.  The maximum
  916. X    length of a name in a directory is MAXNAMELEN.
  917. X  
  918. X    The macro DIRSIZ(dp) gives the amount of space required to represent a
  919. X    directory entry.  Free space in a directory is represented by entries
  920. X    that have dp->d_reclen > DIRSIZ(dp).  All DIRBLKSIZ bytes in a
  921. X    directory block are claimed by the directory entries; this usually
  922. X    results in the last entry in a directory having a large dp->d_reclen.
  923. X    When entries are deleted from a directory, the space is returned to the
  924. X    previous entry in the same directory block by increasing its
  925. X    dp->d_reclen.  If the first entry of a directory block is free, then
  926. X    its dp->d_fileno is set to 0; entries other than the first in a
  927. X    directory do not normally have     dp->d_fileno set to 0.
  928. X  
  929. X    prerequisite:    <sys/types.h>
  930. X*/
  931. X
  932. X#if defined(accel) || defined(sun) || defined(vax)
  933. X#define    DIRBLKSIZ    512    /* size of directory block */
  934. X#else
  935. X#ifdef alliant
  936. X#define    DIRBLKSIZ    4096    /* size of directory block */
  937. X#else
  938. X#ifdef gould
  939. X#define    DIRBLKSIZ    1024    /* size of directory block */
  940. X#else
  941. X#ifdef ns32000            /* Dynix System V */
  942. X#define    DIRBLKSIZ    2600    /* size of directory block */
  943. X#else                /* be conservative; multiple blocks are okay
  944. X                 * but fractions are not */
  945. X#define    DIRBLKSIZ    4096    /* size of directory block */
  946. X#endif
  947. X#endif
  948. X#endif
  949. X#endif
  950. X
  951. X#define    MAXNAMELEN    255    /* maximum filename length */
  952. X/* NOTE:  not MAXNAMLEN, which has been preempted by SVR3 <dirent.h> */
  953. X
  954. Xstruct direct {            /* data from read()/_getdirentries() */
  955. X    unsigned long   d_fileno;    /* unique ident of entry */
  956. X    unsigned short  d_reclen;    /* length of this record */
  957. X    unsigned short  d_namlen;    /* length of string in d_name */
  958. X    char            d_name[MAXNAMELEN + 1];    /* NUL-terminated filename */
  959. X};
  960. X
  961. X/*
  962. X    The DIRSIZ macro gives the minimum record length which will hold the
  963. X    directory entry.  This requires the amount of space in a (struct
  964. X    direct) without the d_name field, plus enough space for the name with a
  965. X    terminating NUL character, rounded up to a (long) boundary.
  966. X  
  967. X    (Note that Berkeley didn't properly compensate for struct padding,
  968. X    but we nevertheless have to use the same size as the actual system.)
  969. X*/
  970. X
  971. X#define    DIRSIZ( dp )    ((sizeof(struct direct) - (MAXNAMELEN+1) \
  972. X            + sizeof(long) + (dp)->d_namlen) \
  973. X            / sizeof(long) * sizeof(long))
  974. X
  975. X#else
  976. X#include    <sys/dir.h>
  977. X#ifdef SYSV3
  978. X#undef    MAXNAMLEN        /* avoid conflict with SVR3 */
  979. X#endif
  980. X /* Good thing we don't need to use the DIRSIZ() macro! */
  981. X#ifdef d_ino            /* 4.3BSD/NFS using d_fileno */
  982. X#undef    d_ino            /* (not absolutely necessary) */
  983. X#else
  984. X#define    d_fileno    d_ino    /* (struct direct) member */
  985. X#endif
  986. X#endif
  987. X#ifdef UNK
  988. X#ifndef UFS
  989. X#include "***** ERROR ***** UNK applies only to UFS"
  990. X/* One could do something similar for getdirentries(), but I didn't bother. */
  991. X#endif
  992. X#include    <signal.h>
  993. X#endif
  994. X
  995. X#if defined(UFS) + defined(BFS) + defined(NFS) != 1    /* sanity check */
  996. X#include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined"
  997. X#endif
  998. X
  999. X#ifdef UFS
  1000. X#define    RecLen( dp )    (sizeof(struct direct))    /* fixed-length entries */
  1001. X#else                /* BFS || NFS */
  1002. X#define    RecLen( dp )    ((dp)->d_reclen)    /* variable-length entries */
  1003. X#endif
  1004. X
  1005. X#ifdef NFS
  1006. X#ifdef BSD_SYSV
  1007. X#define    getdirentries    _getdirentries    /* package hides this system call */
  1008. X#endif
  1009. Xextern int      getdirentries();
  1010. Xstatic long     dummy;        /* getdirentries() needs basep */
  1011. X#define    GetBlock( fd, buf, n )    getdirentries( fd, buf, (unsigned)n, &dummy )
  1012. X#else                /* UFS || BFS */
  1013. X#ifdef BSD_SYSV
  1014. X#define read    _read        /* avoid emulation overhead */
  1015. X#endif
  1016. Xextern int      read();
  1017. X#define    GetBlock( fd, buf, n )    read( fd, buf, (unsigned)n )
  1018. X#endif
  1019. X
  1020. X#ifdef UNK
  1021. Xextern int      _getdents();    /* actual system call */
  1022. X#endif
  1023. X
  1024. Xextern char    *strncpy();
  1025. Xextern int      fstat();
  1026. Xextern OFFSET   lseek();
  1027. X
  1028. Xextern int      errno;
  1029. X
  1030. X#ifndef DIRBLKSIZ
  1031. X#define    DIRBLKSIZ    4096    /* directory file read buffer size */
  1032. X#endif
  1033. X
  1034. X#ifndef NULL
  1035. X#define    NULL    0
  1036. X#endif
  1037. X
  1038. X#ifndef SEEK_CUR
  1039. X#define    SEEK_CUR    1
  1040. X#endif
  1041. X
  1042. X#ifndef S_ISDIR            /* macro to test for directory file */
  1043. X#define    S_ISDIR( mode )        (((mode) & S_IFMT) == S_IFDIR)
  1044. X#endif
  1045. X
  1046. X
  1047. X#ifndef SEEK_CUR
  1048. X#define    SEEK_CUR    1
  1049. X#endif
  1050. X
  1051. X#ifdef BSD_SYSV
  1052. X#define open    _open        /* avoid emulation overhead */
  1053. X#endif
  1054. X
  1055. Xextern int      getdents();    /* SVR3 system call, or emulation */
  1056. X
  1057. Xtypedef char   *pointer;    /* (void *) if you have it */
  1058. X
  1059. Xextern void     free();
  1060. Xextern pointer  malloc();
  1061. Xextern int
  1062. Xopen(), close(), fstat();
  1063. X
  1064. Xextern int      errno;
  1065. Xextern OFFSET   lseek();
  1066. X
  1067. X#ifndef SEEK_SET
  1068. X#define    SEEK_SET    0
  1069. X#endif
  1070. X
  1071. Xtypedef int     bool;        /* Boolean data type */
  1072. X#define    false    0
  1073. X#define    true    1
  1074. X
  1075. X
  1076. X#ifndef NULL
  1077. X#define    NULL    0
  1078. X#endif
  1079. X
  1080. X#ifndef O_RDONLY
  1081. X#define    O_RDONLY    0
  1082. X#endif
  1083. X
  1084. X#ifndef S_ISDIR            /* macro to test for directory file */
  1085. X#define    S_ISDIR( mode )        (((mode) & S_IFMT) == S_IFDIR)
  1086. X#endif
  1087. X
  1088. X#ifdef __STDC__
  1089. X
  1090. XDIR *opendir(char *dirname)
  1091. X
  1092. X#else
  1093. X    
  1094. XDIR *opendir(dirname)
  1095. Xchar           *dirname;    /* name of directory */
  1096. X
  1097. X#endif
  1098. X{
  1099. X    register DIR   *dirp;    /* -> malloc'ed storage */
  1100. X    register int    fd;        /* file descriptor for read */
  1101. X    struct stat     sbuf;    /* result of fstat() */
  1102. X
  1103. X    if ((fd = open(dirname, O_RDONLY)) < 0)
  1104. X    return NULL;        /* errno set by open() */
  1105. X
  1106. X    if (fstat(fd, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) {
  1107. X    close(fd);
  1108. X    errno = ENOTDIR;
  1109. X    return NULL;        /* not a directory */
  1110. X    }
  1111. X    if ((dirp = (DIR *) malloc(sizeof(DIR))) == NULL
  1112. X    || (dirp->dd_buf = (char *) malloc((unsigned) DIRBUF)) == NULL
  1113. X    ) {
  1114. X    register int    serrno = errno;
  1115. X    /* errno set to ENOMEM by sbrk() */
  1116. X
  1117. X    if (dirp != NULL)
  1118. X        free((pointer) dirp);
  1119. X
  1120. X    close(fd);
  1121. X    errno = serrno;
  1122. X    return NULL;        /* not enough memory */
  1123. X    }
  1124. X    dirp->dd_fd = fd;
  1125. X    dirp->dd_loc = dirp->dd_size = 0;    /* refill needed */
  1126. X
  1127. X    return dirp;
  1128. X}
  1129. X
  1130. X
  1131. X/*
  1132. X *    closedir -- close a directory stream
  1133. X *
  1134. X *    last edit:    11-Nov-1988    D A Gwyn
  1135. X */
  1136. X
  1137. X#ifdef __STDC__
  1138. X
  1139. Xint closedir(register DIR *dirp)
  1140. X
  1141. X#else
  1142. X    
  1143. Xint closedir(dirp)
  1144. Xregister DIR    *dirp;        /* stream from opendir() */
  1145. X
  1146. X#endif
  1147. X{
  1148. X    register int    fd;
  1149. X
  1150. X    if ( dirp == NULL || dirp->dd_buf == NULL ) {
  1151. X    errno = EFAULT;
  1152. X    return -1;            /* invalid pointer */
  1153. X    }
  1154. X
  1155. X    fd = dirp->dd_fd;            /* bug fix thanks to R. Salz */
  1156. X    free( (pointer)dirp->dd_buf );
  1157. X    free( (pointer)dirp );
  1158. X    return close( fd );
  1159. X}
  1160. X
  1161. X
  1162. X/*
  1163. X    readdir -- read next entry from a directory stream
  1164. X  
  1165. X    last edit:    25-Apr-1987    D A Gwyn
  1166. X*/
  1167. X
  1168. X#ifdef __STDC__
  1169. X
  1170. Xstruct dirent  *readdir(register DIR *dirp)
  1171. X
  1172. X#else
  1173. X    
  1174. Xstruct dirent  *readdir(dirp)
  1175. Xregister DIR   *dirp;        /* stream from opendir() */
  1176. X
  1177. X#endif
  1178. X{
  1179. X    register struct dirent *dp;    /* -> directory data */
  1180. X
  1181. X    if (dirp == NULL || dirp->dd_buf == NULL) {
  1182. X    errno = EFAULT;
  1183. X    return NULL;        /* invalid pointer */
  1184. X    }
  1185. X    do {
  1186. X    if (dirp->dd_loc >= dirp->dd_size)    /* empty or obsolete */
  1187. X        dirp->dd_loc = dirp->dd_size = 0;
  1188. X
  1189. X    if (dirp->dd_size == 0    /* need to refill buffer */
  1190. X        && (dirp->dd_size =
  1191. X        getdents(dirp->dd_fd, dirp->dd_buf, (unsigned) DIRBUF)
  1192. X        ) <= 0
  1193. X        )
  1194. X        return NULL;    /* EOF or error */
  1195. X
  1196. X    dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc];
  1197. X    dirp->dd_loc += dp->d_reclen;
  1198. X    }
  1199. X    while (dp->d_ino == 0L);    /* don't rely on getdents() */
  1200. X
  1201. X    return dp;
  1202. X}
  1203. X
  1204. X
  1205. X/*
  1206. X    seekdir -- reposition a directory stream
  1207. X  
  1208. X    last edit:    24-May-1987    D A Gwyn
  1209. X  
  1210. X    An unsuccessful seekdir() will in general alter the current
  1211. X    directory position; beware.
  1212. X  
  1213. X    NOTE:    4.nBSD directory compaction makes seekdir() & telldir()
  1214. X        practically impossible to do right.  Avoid using them!
  1215. X*/
  1216. X
  1217. X#ifdef __STDC__
  1218. X
  1219. Xvoid seekdir(register DIR *dirp, register OFFSET loc)
  1220. X
  1221. X#else
  1222. X    
  1223. Xvoid seekdir(dirp, loc)
  1224. Xregister DIR   *dirp;        /* stream from opendir() */
  1225. Xregister OFFSET  loc;        /* position from telldir() */
  1226. X
  1227. X#endif
  1228. X{
  1229. X    register bool   rewind;    /* "start over when stymied" flag */
  1230. X
  1231. X    if (dirp == NULL || dirp->dd_buf == NULL) {
  1232. X    errno = EFAULT;
  1233. X    return;            /* invalid pointer */
  1234. X    }
  1235. X    /*
  1236. X     * A (struct dirent)'s d_off is an invented quantity on 4.nBSD
  1237. X     * NFS-supporting systems, so it is not safe to lseek() to it. 
  1238. X     */
  1239. X
  1240. X    /* Monotonicity of d_off is heavily exploited in the following. */
  1241. X
  1242. X    /*
  1243. X     * This algorithm is tuned for modest directory sizes.  For huge
  1244. X     * directories, it might be more efficient to read blocks until the first
  1245. X     * d_off is too large, then back up one block, or even to use binary
  1246. X     * search on the directory blocks.  I doubt that the extra code for that
  1247. X     * would be worthwhile. 
  1248. X     */
  1249. X
  1250. X    if (dirp->dd_loc >= dirp->dd_size    /* invalid index */
  1251. X    || ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off > loc
  1252. X    /* too far along in buffer */
  1253. X    )
  1254. X    dirp->dd_loc = 0;    /* reset to beginning of buffer */
  1255. X    /* else save time by starting at current dirp->dd_loc */
  1256. X
  1257. X    for (rewind = true;;) {
  1258. X    register struct dirent *dp;
  1259. X
  1260. X    /* See whether the matching entry is in the current buffer. */
  1261. X
  1262. X    if ((dirp->dd_loc < dirp->dd_size    /* valid index */
  1263. X         || readdir(dirp) != NULL    /* next buffer read */
  1264. X         && (dirp->dd_loc = 0, true)    /* beginning of buffer set */
  1265. X         )
  1266. X        && (dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off
  1267. X        <= loc        /* match possible in this buffer */
  1268. X        ) {
  1269. X        for ( /* dp initialized above */ ;
  1270. X         (char *) dp < &dirp->dd_buf[dirp->dd_size];
  1271. X         dp = (struct dirent *) ((char *) dp + dp->d_reclen)
  1272. X        )
  1273. X        if (dp->d_off == loc) {    /* found it! */
  1274. X            dirp->dd_loc =
  1275. X            (char *) dp - dirp->dd_buf;
  1276. X            return;
  1277. X        }
  1278. X        rewind = false;    /* no point in backing up later */
  1279. X        dirp->dd_loc = dirp->dd_size;    /* set end of buffer */
  1280. X    } else
  1281. X     /* whole buffer past matching entry */ if (!rewind) {    /* no point in searching
  1282. X                                 * further */
  1283. X        errno = EINVAL;
  1284. X        return;        /* no entry at specified loc */
  1285. X    } else {        /* rewind directory and start over */
  1286. X        rewind = false;    /* but only once! */
  1287. X
  1288. X        dirp->dd_loc = dirp->dd_size = 0;
  1289. X
  1290. X        if (lseek(dirp->dd_fd, (OFFSET) 0, SEEK_SET)
  1291. X        != 0
  1292. X        )
  1293. X        return;        /* errno already set (EBADF) */
  1294. X
  1295. X        if (loc == 0)
  1296. X        return;        /* save time */
  1297. X    }
  1298. X    }
  1299. X}
  1300. X
  1301. X
  1302. X/* telldir - report directory stream position
  1303. X *
  1304. X * DESCRIPTION
  1305. X *
  1306. X *    Returns the offset of the next directory entry in the
  1307. X *    directory associated with dirp.
  1308. X *
  1309. X *    NOTE:    4.nBSD directory compaction makes seekdir() & telldir()
  1310. X *        practically impossible to do right.  Avoid using them!
  1311. X *
  1312. X * PARAMETERS
  1313. X *
  1314. X *    DIR    *dirp    - stream from opendir()
  1315. X *
  1316. X * RETURNS
  1317. X *
  1318. X *     Return offset of next entry 
  1319. X */
  1320. X
  1321. X
  1322. X#ifdef __STDC__
  1323. X
  1324. XOFFSET telldir(DIR *dirp)
  1325. X
  1326. X#else
  1327. X    
  1328. XOFFSET telldir(dirp)            
  1329. XDIR            *dirp;        /* stream from opendir() */
  1330. X
  1331. X#endif
  1332. X{
  1333. X    if (dirp == NULL || dirp->dd_buf == NULL) {
  1334. X    errno = EFAULT;
  1335. X    return -1;        /* invalid pointer */
  1336. X    }
  1337. X    if (dirp->dd_loc < dirp->dd_size)    /* valid index */
  1338. X    return ((struct dirent *) & dirp->dd_buf[dirp->dd_loc])->d_off;
  1339. X    else            /* beginning of next directory block */
  1340. X    return lseek(dirp->dd_fd, (OFFSET) 0, SEEK_CUR);
  1341. X}
  1342. X
  1343. X
  1344. X#ifdef UFS
  1345. X
  1346. X/*
  1347. X    The following routine is necessary to handle DIRSIZ-long entry names.
  1348. X    Thanks to Richard Todd for pointing this out.
  1349. X*/
  1350. X
  1351. X
  1352. X/* return # chars in embedded name */
  1353. X
  1354. X#ifdef __STDC__
  1355. X
  1356. Xstatic int NameLen(char *name)
  1357. X
  1358. X#else
  1359. X    
  1360. Xstatic int NameLen(name)
  1361. Xchar            *name;        /* -> name embedded in struct direct */
  1362. X
  1363. X#endif
  1364. X{
  1365. X    register char  *s;        /* -> name[.] */
  1366. X    register char  *stop = &name[DIRSIZ];    /* -> past end of name field */
  1367. X
  1368. X    for (s = &name[1];        /* (empty names are impossible) */
  1369. X     *s != '\0'        /* not NUL terminator */
  1370. X     && ++s < stop;        /* < DIRSIZ characters scanned */
  1371. X    );
  1372. X
  1373. X    return s - name;        /* # valid characters in name */
  1374. X}
  1375. X
  1376. X#else                /* BFS || NFS */
  1377. X
  1378. Xextern int      strlen();
  1379. X
  1380. X#define    NameLen( name )    strlen( name )    /* names are always NUL-terminated */
  1381. X
  1382. X#endif
  1383. X
  1384. X#ifdef UNK
  1385. Xstatic enum {
  1386. X    maybe, no, yes
  1387. X} state = maybe;
  1388. X
  1389. X
  1390. X/* sig_catch - used to catch signals
  1391. X *
  1392. X * DESCRIPTION
  1393. X *
  1394. X *    Used to catch signals.
  1395. X */
  1396. X
  1397. X/*ARGSUSED*/
  1398. X
  1399. X#ifdef __STDC__
  1400. X
  1401. Xstatic void sig_catch(int sig)
  1402. X
  1403. X#else
  1404. X    
  1405. Xstatic void sig_catch(sig)
  1406. Xint             sig;        /* must be SIGSYS */
  1407. X
  1408. X#endif
  1409. X{
  1410. X    state = no;            /* attempted _getdents() faulted */
  1411. X}
  1412. X#endif
  1413. X
  1414. X
  1415. X/* getdents - get directory entries
  1416. X *
  1417. X * DESCRIPTION
  1418. X *
  1419. X *    Gets directory entries from the filesystem in an implemenation
  1420. X *    defined way.
  1421. X *
  1422. X * PARAMETERS
  1423. X *
  1424. X *    int             fildes    - directory file descriptor 
  1425. X *    char           *buf    - where to put the (struct dirent)s 
  1426. X *    unsigned    nbyte    - size of buf[] 
  1427. X *
  1428. X * RETURNS
  1429. X * 
  1430. X *    Returns number of bytes read; 0 on EOF, -1 on error 
  1431. X */
  1432. X
  1433. X#ifdef __STDC__
  1434. X
  1435. Xint getdents(int fildes, char *buf, unsigned nbyte)
  1436. X
  1437. X#else
  1438. X    
  1439. Xint getdents(fildes, buf, nbyte)    
  1440. Xint             fildes;        /* directory file descriptor */
  1441. Xchar           *buf;        /* where to put the (struct dirent)s */
  1442. Xunsigned        nbyte;        /* size of buf[] */
  1443. X
  1444. X#endif
  1445. X{
  1446. X    int             serrno;    /* entry errno */
  1447. X    OFFSET          offset;    /* initial directory file offset */
  1448. X    struct stat     statb;    /* fstat() info */
  1449. X    union {
  1450. X    /* directory file block buffer */
  1451. X#ifdef UFS
  1452. X    char        dblk[DIRBLKSIZ + 1];
  1453. X#else
  1454. X    char            dblk[DIRBLKSIZ];
  1455. X#endif
  1456. X    struct direct   dummy;    /* just for alignment */
  1457. X    } u;        /* (avoids having to malloc()) */
  1458. X    register struct direct *dp;    /* -> u.dblk[.] */
  1459. X    register struct dirent *bp;    /* -> buf[.] */
  1460. X
  1461. X#ifdef UNK
  1462. X    switch (state) {
  1463. X    SIG_T         (*shdlr)();    /* entry SIGSYS handler */
  1464. X    register int    retval;        /* return from _getdents() if any */
  1465. X
  1466. X    case yes:            /* _getdents() is known to work */
  1467. X    return _getdents(fildes, buf, nbyte);
  1468. X
  1469. X    case maybe:        /* first time only */
  1470. X    shdlr = signal(SIGSYS, sig_catch);
  1471. X    retval = _getdents(fildes, buf, nbyte);    /* try it */
  1472. X    signal(SIGSYS, shdlr);
  1473. X
  1474. X    if (state == maybe) {    /* SIGSYS did not occur */
  1475. X        state = yes;    /* so _getdents() must have worked */
  1476. X        return retval;
  1477. X    }
  1478. X    /* else fall through into emulation */
  1479. X
  1480. X/*    case no:    /* fall through into emulation */
  1481. X    }
  1482. X#endif
  1483. X
  1484. X    if (buf == NULL
  1485. X#ifdef ATT_SPEC
  1486. X    || (unsigned long) buf % sizeof(long) != 0    /* ugh */
  1487. X#endif
  1488. X    ) {
  1489. X    errno = EFAULT;        /* invalid pointer */
  1490. X    return -1;
  1491. X    }
  1492. X    if (fstat(fildes, &statb) != 0) {
  1493. X    return -1;        /* errno set by fstat() */
  1494. X    }
  1495. X
  1496. X    if (!S_ISDIR(statb.st_mode)) {
  1497. X    errno = ENOTDIR;    /* not a directory */
  1498. X    return -1;
  1499. X    }
  1500. X    if ((offset = lseek(fildes, (OFFSET) 0, SEEK_CUR)) < 0) {
  1501. X    return -1;        /* errno set by lseek() */
  1502. X    }
  1503. X
  1504. X#ifdef BFS            /* no telling what remote hosts do */
  1505. X    if ((unsigned long) offset % DIRBLKSIZ != 0) {
  1506. X    errno = ENOENT;        /* file pointer probably misaligned */
  1507. X    return -1;
  1508. X    }
  1509. X#endif
  1510. X
  1511. X    serrno = errno;        /* save entry errno */
  1512. X
  1513. X    for (bp = (struct dirent *) buf; bp == (struct dirent *) buf;) {    
  1514. X
  1515. X        /* convert next directory block */
  1516. X    int             size;
  1517. X
  1518. X    do {
  1519. X        size = GetBlock(fildes, u.dblk, DIRBLKSIZ);
  1520. X    } while (size == -1 && errno == EINTR);
  1521. X
  1522. X    if (size <= 0) {
  1523. X        return size;    /* EOF or error (EBADF) */
  1524. X    }
  1525. X
  1526. X    for (dp = (struct direct *) u.dblk;
  1527. X         (char *) dp < &u.dblk[size];
  1528. X         dp = (struct direct *) ((char *) dp + RecLen(dp))
  1529. X        ) {
  1530. X#ifndef UFS
  1531. X        if (dp->d_reclen <= 0) {
  1532. X        errno = EIO;    /* corrupted directory */
  1533. X        return -1;
  1534. X        }
  1535. X#endif
  1536. X
  1537. X        if (dp->d_fileno != 0) {    /* non-empty; copy to user buffer */
  1538. X        register int    reclen =
  1539. X        DIRENTSIZ(NameLen(dp->d_name));
  1540. X
  1541. X        if ((char *) bp + reclen > &buf[nbyte]) {
  1542. X            errno = EINVAL;
  1543. X            return -1;    /* buf too small */
  1544. X        }
  1545. X        bp->d_ino = dp->d_fileno;
  1546. X        bp->d_off = offset + ((char *) dp - u.dblk);
  1547. X        bp->d_reclen = reclen;
  1548. X
  1549. X        {
  1550. X#ifdef UFS
  1551. X            /* Is the following kludge ugly?  You bet. */
  1552. X
  1553. X            register char   save = dp->d_name[DIRSIZ];
  1554. X            /* save original data */
  1555. X
  1556. X            dp->d_name[DIRSIZ] = '\0';
  1557. X            /* ensure NUL termination */
  1558. X#endif
  1559. X            /* adds NUL padding */
  1560. X            strncpy(bp->d_name, dp->d_name, reclen - DIRENTBASESIZ);
  1561. X#ifdef UFS
  1562. X            dp->d_name[DIRSIZ] = save;
  1563. X            /* restore original data */
  1564. X#endif
  1565. X        }
  1566. X
  1567. X        bp = (struct dirent *) ((char *) bp + reclen);
  1568. X        }
  1569. X    }
  1570. X
  1571. X#ifndef BFS            /* 4.2BSD screwed up; fixed in 4.3BSD */
  1572. X    if ((char *) dp > &u.dblk[size]) {
  1573. X        errno = EIO;    /* corrupted directory */
  1574. X        return -1;
  1575. X    }
  1576. X#endif
  1577. X    }
  1578. X
  1579. X    errno = serrno;        /* restore entry errno */
  1580. X    return (char *) bp - buf;    /* return # bytes read */
  1581. X}
  1582. END_OF_paxdir.c
  1583. if test 16936 -ne `wc -c <paxdir.c`; then
  1584.     echo shar: \"paxdir.c\" unpacked with wrong size!
  1585. fi
  1586. # end of overwriting check
  1587. fi
  1588. echo shar: End of archive 5 \(of 6\).
  1589. cp /dev/null ark5isdone
  1590. MISSING=""
  1591. for I in 1 2 3 4 5 6 ; do
  1592.     if test ! -f ark${I}isdone ; then
  1593.     MISSING="${MISSING} ${I}"
  1594.     fi
  1595. done
  1596. if test "${MISSING}" = "" ; then
  1597.     echo You have unpacked all 6 archives.
  1598.     rm -f ark[1-9]isdone
  1599. else
  1600.     echo You still need to unpack the following archives:
  1601.     echo "        " ${MISSING}
  1602. fi
  1603. ##  End of shell archive.
  1604. exit 0
  1605.  
  1606.